package threadjuc.singleton;

/**
 * @author zxl
 * @version 1.0
 * @date 2021/10/28 17:39
 * 懒汉式
 * 单例可使用反射破环 ，使用枚举反射无法破环
 */
public class LazyMan {

    private static Boolean flag = false;

    /**
     * 私有构造方法
     */
    private LazyMan(){
        synchronized (LazyMan.class){
            if(flag==false){
                flag=true;
            }else {
                System.out.println("反射");
            }
        }
        System.out.println("被调用");
    }

    private volatile static LazyMan lazyMan;

    /**
     * 双重锁  DCL懒汉式
     */
    public static LazyMan getObj(){
        if(lazyMan==null){
            synchronized (LazyMan.class){
                if(lazyMan==null){
                    //会出现指令重排问题
                    lazyMan = new LazyMan();
                    /*
                    1 分配内存空间
                    2 执行构造方法，初始化对象
                    3 把这个对象执行内存空间

                    问题 出现指令重排现象
                         当一个线程执行了1和3，还未执行2时 另一个线程进来判断lazyMan不为空，于是返回了值 但此时该对象还没有被创建出来
                    解决 将lazyMan 加volatile关键字，禁止指令重排
                     */
                }
            }
        }
        return lazyMan;
    }

    public static void main(String[] args) {
        for (int i = 0; i < 20; i++) {
            new Thread(()->{
                getObj();
            }).start();
        }
    }
}
